package com.jweb.framework.ws.sdo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;


import commonj.sdo11.DataObject;
import commonj.sdo11.Property;
import commonj.sdo11.Type;

/**
 * 修改人： Thomas
 * 修改内容：新增 
 * 类说明：DataObject 类型数据与 MAP 类型数据互转
 */
public class DefaultSdoConverter implements SdoConverter {
	
	private SdoConverter.Mapping mapping ;
	private boolean useToDataDefault ;
	private boolean useToSdoDefault ;
	private boolean outputNull ;
	
	public void setDataFlatting(boolean flag){
		if(this.mapping != null){
			throw new IllegalArgumentException("mapping has been setted by setMapping.");
		}
		if(flag){
			this.mapping = FLATTING ;
		}
		else {
			this.mapping = CASCADE ;
		}
	}
	
	public void setMapping(SdoConverter.Mapping mapping){
		this.mapping = mapping ;
	}
	
	private SdoConverter.Mapping mapping(){
		if(this.mapping == null){
			return FLATTING ;
		}
		return this.mapping ;
	}
	
	public void setUseToDataDefault(boolean flag){
		this.useToDataDefault = flag ;
	}
	
	public void setUseToSdoDefault(boolean flag){
		this.useToSdoDefault = flag ;
	}
	
	public void setOutputNull(boolean flag){
		this.outputNull = flag ;
	}
	/**
	 * 将DataObject数据类型转换成MAP键值对
	 */
	public Map toData(DataObject dataObject){
		
		HashMap hashMap = new HashMap();
		if(dataObject == null){
			return hashMap ;
		}
		Stack stack = new Stack();
		parseDataObjectToMap(dataObject , hashMap , stack);
		mapping().setDataMap(null , hashMap , null , null);
		return hashMap ;
	}
	
	private void parseDataObjectToMap(DataObject dataObject , HashMap hashMap , Stack stack){
		Type type = dataObject.getType();
		List list = type.getProperties();
		
		int i = 0 ;
		for(int j = list.size() ; i < j ; ++i){
			Property property = (Property)list.get(i);
			String s = property.getName();
			if(property.isMany()){
				List list1 = dataObject.getList(i);
				if((list1 != null) && (list1.size()>0)){
					ArrayList arrayList = new ArrayList();
					stack.push(s);
					int k = 0 ;
					for(int l = list1.size() ; k < l ; k++){
						Object obj1 = list1.get(k);
						if(!property.isContainment()){
							obj1 = parseDataObject(obj1 , property);
							if(obj1 != null){
								arrayList.add(obj1);
							}
						}
						else if(obj1 != null){
							HashMap hashMap1 = new HashMap();
							arrayList.add(hashMap1);
							parseDataObjectToMap((DataObject)obj1 , hashMap1 , stack);
						}
					}
					
					stack.pop();
					mapping().setDataValue(s , hashMap, arrayList , stack);
				}
			}
			else {
				Object obj = dataObject.isSet(i) ? dataObject.get(i) : null ;
				if(!property.isContainment()){
					obj = parseDataObject(obj , property);
					if(obj != null){
						mapping().setDataValue(s, hashMap, obj, stack);
					}
				}
				else if(obj != null){
					HashMap hashMap1 = new HashMap();
					stack.push(s);
					parseDataObjectToMap((DataObject)obj , hashMap1 , stack);
					stack.pop();
					mapping().setDataMap(s, hashMap, hashMap1, stack);
				}
			}
		}
	}
	
	private Object parseDataObject(Object obj , Property property){
		
		if((obj == null) && useToDataDefault){
			obj = property.getDefault();
		}
		if(obj != null){
			obj = SdoTypeUtils.toData(property.getType() , obj);
		}
		
		return obj ;
	}
	
	/**
	 * 将 MAP 数据类型转换成 DataObject数据类型
	 */
	public DataObject toSdo(Map map , DataObject dataObject){
		if((dataObject == null) || map == null){
			return null ;
		}
		else {
			Stack stack = new Stack();
			map = mapping().getSdoMap(null , map, null);
			parseMapToDataObject(dataObject , map , stack);
			return dataObject ;
		}
	}
	
	private void parseMapToDataObject(DataObject dataObject , Map map , Stack stack){
		Type type = dataObject.getType();
		List list = type.getProperties();
		int i = 0 ;
		for(int j = list.size() ; i < j ; i++){
			Property property = (Property) list.get(i); 
			String s = property.getName() ; 
			//System.out.println("------------------------------ s = " + s);
			if(property.isMany()){ 
				List list1 = (List) mapping().getSdoValue(s, map, stack);
				if(list1 != null && !list1.isEmpty()){
					ArrayList arrayList = new ArrayList();
					stack.push(s);
					int k = 0 ;
					for(int l = list1.size() ; k < l ; k++){
						Object obj1 = list1.get(k);
						if(!property.isContainment()){
							obj1 = parseMap(obj1 , property);
							if(obj1 != null || outputNull){
								arrayList.add(obj1);
							}
						}
						else if(obj1 != null){
							DataObject dataObject3 = mapping().createObject((Map) obj1, dataObject, property);
							arrayList.add(dataObject3);
							parseMapToDataObject(dataObject3 , (Map)obj1 , stack);
						}
						else if(outputNull){
							DataObject dataObject4 = dataObject.createDataObject(property);
							arrayList.add(dataObject4);
						}
					}
					
					stack.pop();
					dataObject.setList(i, arrayList);
				}
			}
			else {
				Map map1 = map ;
				if(!property.isContainment()){
					Object obj = mapping().getSdoValue(s, map, stack); 
					obj = parseMap(obj , property); 
					if(obj != null || outputNull){
						dataObject.set(s, obj);
					}
				}
				else {
					Map map2 = mapping().getSdoMap(s, map, stack);
					if(map2 != null){
						DataObject dataObject1 = mapping().createObject(map2, dataObject, property);
						dataObject.set(s, dataObject1); 
						stack.push(s);
						parseMapToDataObject(dataObject1 , map2 , stack);
						stack.pop();
					}
					else if(outputNull){
						DataObject dataObject2 = dataObject.createDataObject(property);
						dataObject.set(s, dataObject2);
					}
				}
			}
		}
	}
	
	private Object parseMap(Object obj , Property property){
		if(obj == null && useToSdoDefault){
			obj = property.getDefault();
		}
		if(obj != null){
			obj = SdoTypeUtils.toDso(property.getType(), obj);
		}
		
		return obj ;
	}
	
}
